﻿using System;
using System.Collections.Generic;
using CustomerContactSystem.Core.Model;
using NHibernate.Criterion;

namespace CustomerContactSystem.Core.AppServices.Query {
    public class EnquirySearchQuery {
        public int EnquiryId { get; set; }
        public int EnquiryTypeId { get; set; }
        public int FixYourStreetId { get; set; }
        public int ClassificationId { get; set; }
        public DateTime ReceivedFrom { get; set; }
        public DateTime ReceivedTo { get; set; }
        public DateTime DeadlineFrom { get; set; }
        public DateTime DeadlineTo { get; set; }
        public int EnquiryStatusId { get; set; }
        public int EnquirySourceId { get; set; }
        public int LoggedByUserId { get; set; }
        public int LoggedByDepartmentId { get; set; }
        public int LoggedByGroupId { get; set; }
        public int CurrentlyReferredToId { get; set; }
        public int CurrentlyReferredToDepartmentId { get; set; }
        public int CurrentlyReferredToGroupId { get; set; }
        public int EverReferredToId { get; set; }
        public int CategoryId { get; set; }
        public bool MediaOnly { get; set; }
        public int TagId { get; set; }
        public int OrderBy { get; set; }
        public bool Ascending { get; set; }
        public List<int> EnquiryIds { get; set; }

        public QueryOver<Enquiry> Result() {
            var enquiries = QueryOver.Of<Enquiry>();

            enquiries = enquiries.Where(e => e.Deletion == null);

            if (EnquiryId > 0) {
                return enquiries.Where(e => e.Id == EnquiryId);
            }

            switch (EnquiryTypeId) {
                case 1:
                    enquiries = enquiries.Where(e => e.FirstReferral != null);
                    break;
                case 2:
                    enquiries = enquiries.Where(e => e.FirstReferral == null);
                    break;
            }

            if (FixYourStreetId > 0) {
                return enquiries.Where(e => e.FixYourStreetId == FixYourStreetId);
            }

            if (ClassificationId > 0) {
                enquiries = enquiries.Where(e => e.Classification.Id == EnquiryTypeId);
            }

            if (ReceivedFrom != DateTime.MinValue) {
                enquiries = enquiries.Where(e => e.DateOfEnquiry >= ReceivedFrom);
            }

            if (ReceivedTo != DateTime.MinValue) {
                enquiries = enquiries.Where(e => e.DateOfEnquiry <= ReceivedTo);
            }

            if (DeadlineFrom != DateTime.MinValue)
            {
                enquiries = enquiries.Where(e => e.Deadline >= DeadlineFrom);
            }

            if (DeadlineTo != DateTime.MinValue)
            {
                enquiries = enquiries.Where(e => e.Deadline <= DeadlineTo);
            }

            if (EnquiryStatusId > 0) {
                switch (EnquiryStatusId) {                        
                    case 1 :
                        enquiries = enquiries.Where(e => e.Closure == null);
                        break;
                    case 2 :
                        enquiries = enquiries.Where(e => e.Closure == null && e.Deadline < DateTime.Now);
                        break;
                    case 3:
                        enquiries = enquiries.Where(e => e.Closure == null && e.Deadline > DateTime.Now);
                        break;
                    case 4:
                        enquiries = enquiries.Where(e => e.Closure != null);
                        break;
                    case 5:
                        EnquiryClosure cAlias = null;
                        enquiries = enquiries.JoinAlias(e => e.Closure, () => cAlias).Where(() => cAlias.DeadlineMet);                            
                        break;
                    case 6:
                        EnquiryClosure cAlias2 = null;
                        enquiries = enquiries.JoinAlias(e => e.Closure, () => cAlias2).Where(() => !cAlias2.DeadlineMet);
                        break;
                }
            }

            if (EnquirySourceId > 0) {
                enquiries = enquiries.Where(e => e.Source.Id == EnquirySourceId);
            }

            if (LoggedByUserId > 0) {
                enquiries = enquiries.Where(e => e.SubmittedBy.Id == LoggedByUserId);
            }
            else {
                if (LoggedByDepartmentId > 0) {
                    enquiries = enquiries.Where(e => e.SubmittedByDepartment.Id == LoggedByDepartmentId);
                }
                if (LoggedByGroupId > 0) {
                    enquiries = enquiries.Where(e => e.SubmittedByGroup.Id == LoggedByGroupId);
                }
            }

            if (CurrentlyReferredToId > 0) {
                EnquiryCurrentReferral refAlias = null;
                enquiries =
                    enquiries.JoinAlias(e => e.CurrentReferral, () => refAlias).Where(
                        () => refAlias.CurrentlyReferredTo.Id == CurrentlyReferredToId);
            }
            else {
                if (CurrentlyReferredToDepartmentId > 0) {
                    EnquiryCurrentReferral refAlias = null;    
                    enquiries =
                        enquiries.JoinAlias(e => e.CurrentReferral, () => refAlias).Where(
                            () => refAlias.CurrentlyReferredToDepartment.Id == CurrentlyReferredToDepartmentId);
                }
                if (CurrentlyReferredToGroupId > 0) {
                    EnquiryCurrentReferral refAlias = null;    
                    enquiries =
                        enquiries.JoinAlias(e => e.CurrentReferral, () => refAlias).Where(
                            () => refAlias.CurrentlyReferredToGroup.Id == CurrentlyReferredToGroupId);
                }
            }

            if (EverReferredToId > 0) {
                if (EnquiryIds.Count == 0) {
                    EnquiryIds.Add(0);
                }
                enquiries = enquiries.Where(e => e.SubmittedBy.Id == EverReferredToId || e.Id.IsIn(EnquiryIds));
            }

            if (CategoryId > 0) {
                enquiries = enquiries.Where(e => e.Category.Id == CategoryId);
            }

            if (MediaOnly) {
                enquiries = enquiries.Where(e => e.IsMediaEnquiry);
            }

            if (TagId > 0) {
                Tag tagAlias = null;
                enquiries =
                    enquiries.JoinAlias(e => e.Tags, () => tagAlias).Where(() => tagAlias.Id == TagId);
            }

            if (Ascending) {
                if (OrderBy == 0) {
                    enquiries = enquiries.OrderBy(e => e.DateOfEnquiry).Asc;
                }
                else {
                    switch (OrderBy) {
                        case 1:
                            enquiries = enquiries.OrderBy(e => e.Deadline).Asc;
                            break;
                        case 2:
                            enquiries = enquiries.OrderBy(e => e.Id).Asc;
                            break;
                    }
                }
            }
            else
            {
                if (OrderBy == 0)
                {
                    enquiries = enquiries.OrderBy(e => e.DateOfEnquiry).Desc;
                }
                else
                {
                    switch (OrderBy)
                    {
                        case 1:
                            enquiries = enquiries.OrderBy(e => e.Deadline).Desc;
                            break;
                        case 2:
                            enquiries = enquiries.OrderBy(e => e.Id).Desc;
                            break;
                    }
                }
            }

            return enquiries;
        }
    }
}